﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace Pavilion.DesignerTool
{
    public class DrawingBoardXnaComponent : IXnaComponent
    {
        private Render render;

        public Vector2 CenterPosition { get; private set; }
        public IDrawTool DrawTool { get; set; }
        public AnimationSelectionInfo AnimationSelectionInfo { get; set; }
        public float Scale { get; set; }
        public FrameData CurrentFrameData { get { return (AnimationSelectionInfo != null) ? AnimationSelectionInfo.CurrentFrameData : null; } }
        private Vector2 CurrentFrameOrigin { get { return new Vector2(CurrentFrameData.Frame.OriginX * Scale, CurrentFrameData.Frame.OriginY * Scale); } }

        public DrawingBoardXnaComponent()
        {
            render = new Render();
        }

        public void Load(GraphicsDevice graphics, IServiceProvider services) { }
        public void Update(GameTime gametime) { }

        public void Draw()
        {
            DrawBackgroundAnimations();
            DrawCurrentAnimation();
        }

        private void DrawBackgroundAnimations()
        {
            foreach (AnimationLayer animationLayer in AnimationSelectionInfo.BackgroundAnimationCollection)
            {
                int startingIndex = DetermineStartingIndex(animationLayer);
                int endingIndex = DetermineEndingIndex(animationLayer);

                for (int i = startingIndex; i <= endingIndex; i++)
                    animationLayer.CurrentAnimationData.FrameDataCollection[i].Frame.DrawOnScreen(DeterminePositionOfIndex(animationLayer, i), new Color(255, 255, 255, 100), Scale, SpriteEffects.None);
            }
        }

        private void DrawCurrentAnimation()
        {
            if (CurrentFrameData == null)
                return;

            int startingIndex = DetermineStartingIndex(AnimationSelectionInfo.CurrentAnimationLayer);
            int endingIndex = DetermineEndingIndex(AnimationSelectionInfo.CurrentAnimationLayer);

            for (int i = startingIndex; i <= endingIndex; i++)
            {
                if (i != AnimationSelectionInfo.CurrentFrameIndex)
                    AnimationSelectionInfo.CurrentAnimationData.FrameDataCollection[i].Frame.DrawOnScreen(DeterminePositionOfIndex(AnimationSelectionInfo.CurrentAnimationLayer, i), new Color(255, 255, 255, 100), Scale, SpriteEffects.None);
            }

            CurrentFrameData.Frame.DrawOnScreen(CenterPosition, Color.White, Scale, SpriteEffects.None);
            CurrentFrameData.Frame.DrawBoundingBoxOnScreen(Color.Black, Scale);
        }

        public void SizeChanged(double width, double height)
        {
            CenterPosition = new Vector2((int)width / 2, (int)height / 2);
        }

        public void RenderPoint(System.Windows.Point point, CTexture2D currentLayer, float pressurePercentage)
        {
            if (DrawTool == null)
                return;

            render.Begin(currentLayer.Width, currentLayer.Height);

            DrawManager.Instance.DrawOnScreen(currentLayer.TextureItem, new Vector2(0, 0), new Rectangle(0, 0, currentLayer.Width, currentLayer.Height), Color.White);
            DrawTool.Draw(new System.Windows.Point(point.X, point.Y), pressurePercentage);

            render.End();

            currentLayer.TextureItem = render.Texture;
        }

        public void RenderLine(System.Windows.Point start, System.Windows.Point end, CTexture2D currentLayer, float pressurePercentage)
        {
            if (DrawTool == null)
                return;

            double distance, width, height, xSlope, ySlope;

            width = end.X - start.X;
            height = end.Y - start.Y;
            distance = (float)Math.Sqrt((double)((height * height) + (width * width)));
            xSlope = width / distance;
            ySlope = height / distance;

            render.Begin(currentLayer.Width, currentLayer.Height);

            DrawManager.Instance.DrawOnScreen(currentLayer.TextureItem, new Vector2(0, 0), new Rectangle(0, 0, currentLayer.Width, currentLayer.Height), Color.White);
            for (int i = 0; i <= distance; i++)
                DrawTool.Draw(new System.Windows.Point(start.X + ((double)i * xSlope), start.Y + ((double)i * ySlope)), pressurePercentage);

            render.End();

            currentLayer.TextureItem = render.Texture;
        }

        private Vector2 DeterminePositionOfIndex(AnimationLayer animationLayer, int frameIndex)
        {
            int currentIndex = AnimationSelectionInfo.CurrentIndex - animationLayer.Offset;
            float xPos = CenterPosition.X + (animationLayer.SpeedDistance * (frameIndex - currentIndex) * 10);

            return new Vector2(xPos, CenterPosition.Y);
        }

        private int DetermineStartingIndex(AnimationLayer animationLayer)
        {
            int startingIndex = AnimationSelectionInfo.CurrentIndex - animationLayer.Offset - AnimationSelectionInfo.LeftIndexBounds;

            if (startingIndex > 0)
                return startingIndex;
            else
                return 0;
        }

        private int DetermineEndingIndex(AnimationLayer animationLayer)
        {
            int endingIndex = AnimationSelectionInfo.CurrentIndex - animationLayer.Offset + AnimationSelectionInfo.RightIndexBounds;
            int frameCount = (animationLayer.CurrentAnimationData == null) ? 0 : animationLayer.CurrentAnimationData.FrameDataCollection.Count;

            if (endingIndex < frameCount)
                return endingIndex;
            else
                return frameCount - 1;
        }
    }
}
